<template>
  <div v-show="isOpen" class="chat-panel" ref="root">
    <div class="panel bg-background" :class="{ open: panelOpen }" @transitionend="panelTransitionEnd">
      <div class="head">
        <div class="left"></div>
        <div class="title gap-row-8">
          <Avatar :src="user.avatar" :radius="15" :vip="user.isVip" :vipTier="user.tier"></Avatar>
          <div class="name font-size-16 fone-weight-500 line-height-140">{{ user.nickname }}</div>
        </div>
        <div class="right">
          <Icon class="close pointer" size="24" @click="closePanel" name="close"></Icon>
        </div>
      </div>
      <div class="body">
        <div class="tabs" :class="{ 'active-left': isComment, 'active-right': isChat, swiping }">
          <div class="labels">
            <div
              class="label font-size-14 fone-weight-500 line-height-140 pointer"
              @click="tab = CHAT_PANEL_TAB.COMMENT"
            >
              {{ $t('message.comment') }}
            </div>
            <div class="label font-size-14 fone-weight-500 line-height-140 pointer" @click="tab = CHAT_PANEL_TAB.CHAT">
              {{ $t('message.chat') }}
            </div>
          </div>
          <div class="index bg-primary" :style="indexStyle"></div>
        </div>
        <div v-if="isOpen" class="content" :class="{ 'at-right': isChat, swiping }" ref="content">
          <div
            class="left"
            :style="{ transform: contentTransform, opacity: contentLeftOpacity, transitionDuration }"
            @transitionend.self="resetTransitionDuration"
          >
            <CommentView :feedId="feedId"></CommentView>
          </div>
          <div
            class="right"
            :style="{ transform: contentTransform, opacity: contentRightOpacity, transitionDuration }"
            @transitionend.self="resetTransitionDuration"
          >
            <Room :userId="user.id" keep-translator-more></Room>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useChatPanelStore } from '@/store/chat-panel'
import asyncCompWithLoading from '@/utils/async-comp-with-loading'
import CommentView from '@/components/chat/CommentView.vue'
import Avatar from '@/components/multimedia/Avatar.vue'
import { usePreventTouchmove } from '@/compositions/mobile/preventTouchmove'
import { useSwipe } from '@/compositions/mobile/swipe'
import { CHAT_PANEL_TAB } from '@/constant'

const Room = asyncCompWithLoading(() => import('@/components/chat/Room.vue'))

const chatPanelStore = useChatPanelStore()
const { isOpen, feedId, user } = storeToRefs(chatPanelStore)
const { close: closeChatPanel } = chatPanelStore

const panelOpen = ref(false)
watch(isOpen, (v) => {
  if (v) {
    requestAnimationFrame(openPanel)
  } else {
    tab.value = CHAT_PANEL_TAB.COMMENT
  }
})
function openPanel() {
  panelOpen.value = true
}
function closePanel() {
  panelOpen.value = false
}
function panelTransitionEnd() {
  if (!panelOpen.value) {
    closeChatPanel()
  }
}

const tab = ref(CHAT_PANEL_TAB.COMMENT)
const isComment = computed(() => tab.value === CHAT_PANEL_TAB.COMMENT)
const isChat = computed(() => tab.value === CHAT_PANEL_TAB.CHAT)

const root = ref(null)
usePreventTouchmove(root, (evt) => {
  let currEle = evt.target
  while (true) {
    if (currEle === content.value) {
      return false
    }
    if (currEle === root.value) {
      return true
    }
    currEle = currEle.parentElement
  }
})

const HALF_VIEW_WIDTH = window.innerWidth / 2 - 16
const content = ref(null)

// 滑動操作
const { offset, swiping, transitionDuration, resetTransitionDuration } = useSwipe(content, {
  viewLength: HALF_VIEW_WIDTH * 2,
  isBlockBackward: () => isComment.value,
  isBlockForward: () => isChat.value,
  onBackward: () => (tab.value = CHAT_PANEL_TAB.COMMENT),
  onForward: () => (tab.value = CHAT_PANEL_TAB.CHAT),
})

// 滑動中關閉瀏覽器預設行為
usePreventTouchmove(content, () => offset.value !== 0)

// 滑動時的樣式
const indexStyle = computed(() => {
  if (offset.value > 0) {
    return { transform: `translate(${Math.min(offset.value, HALF_VIEW_WIDTH * 2) / 2}px, -0.109375rem)` }
  } else if (offset.value < 0) {
    return { transform: `translate(calc(100% + ${Math.max(offset.value, -HALF_VIEW_WIDTH * 2) / 2}px), -0.109375rem)` }
  } else {
    return ''
  }
})
const contentTransform = computed(() => {
  if (offset.value > 0) {
    return `translateX(${-Math.min(offset.value, HALF_VIEW_WIDTH * 2)}px)`
  } else if (offset.value < 0) {
    return `translateX(calc(-100% + ${-Math.max(offset.value, -HALF_VIEW_WIDTH * 2)}px))`
  } else {
    return ''
  }
})
const contentLeftOpacity = computed(() => {
  if (offset.value > 0 && isComment.value) {
    const opacity = 1 - offset.value / (HALF_VIEW_WIDTH * 2)
    return Math.max(opacity, 0)
  } else if (offset.value < 0 && isChat.value) {
    const opacity = -offset.value / (HALF_VIEW_WIDTH * 2)
    return Math.min(opacity, 1)
  } else {
    return ''
  }
})
const contentRightOpacity = computed(() => {
  if (offset.value > 0 && isComment.value) {
    const opacity = offset.value / (HALF_VIEW_WIDTH * 2)
    return Math.min(opacity, 1)
  } else if (offset.value < 0 && isChat.value) {
    const opacity = 1 - -offset.value / (HALF_VIEW_WIDTH * 2)
    return Math.max(opacity, 0)
  } else {
    return ''
  }
})
</script>

<style lang="scss" scoped>
.chat-panel {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  z-index: 1; // MediaWall.vue 當中的 tab sticky 時需要設定 z-index，會跟這邊衝突所以這邊也得設定至少同層級
  background-color: rgba(0, 0, 0, 0.6);

  .panel {
    width: 100%;
    height: 33.4375rem;
    max-height: 90%;
    padding: 1rem 1rem 0.5rem;
    position: absolute;
    bottom: 0;
    border-radius: 1.25rem 1.25rem 0 0;
    transform: translateY(100%);
    transition: transform 0.3s ease;

    &.open {
      transform: none;
    }
    &.expand {
      height: 95%;
    }

    .head {
      height: 1.875rem;
      margin-bottom: 1rem;
      display: flex;
      align-items: center;

      .left,
      .right {
        width: 2rem;
      }

      .title {
        flex-grow: 1;
        display: flex;
        justify-content: center;
        align-items: center;
      }
    }

    .body {
      height: calc(100% - 1.875rem - 1rem);

      .tabs {
        margin-bottom: 1rem;
        .labels {
          height: 2rem;
          padding-bottom: 0.5rem;
          border-bottom: 1px solid #fff;
          display: flex;

          .label {
            width: 50%;
            text-align: center;
          }
        }

        .index {
          width: 50%;
          height: 0.15625rem;
          border-radius: 0.1rem;
          transition: transform 0.2s;
        }

        &.active-left {
          .labels .label:first-child {
            color: rgb(var(--v-theme-primary));
          }
          .index {
            transform: translate(0, -0.109375rem);
          }
        }
        &.active-right {
          .labels .label:last-child {
            color: rgb(var(--v-theme-primary));
          }
          .index {
            transform: translate(100%, -0.109375rem);
          }
        }
      }

      .content {
        height: calc(100% - 2rem - 1rem);
        position: relative;
        overflow-x: hidden;

        .left,
        .right {
          width: 100%;
          height: 100%;
          position: absolute;
          top: 0;
          transition: transform 0.25s ease-out, opacity 0.25s ease-out;
        }
        .left {
          opacity: 1;
        }
        .right {
          left: 100%;
          opacity: 0;
        }

        &.at-right {
          .left {
            transform: translateX(-100%);
            opacity: 0;
          }
          .right {
            transform: translateX(-100%);
            opacity: 1;
          }
        }
      }

      .tabs,
      .content {
        &.swiping {
          .index,
          .left,
          .right {
            transition: none;
            will-change: transform, opacity;
          }
        }
      }
    }
  }
}
</style>
